package yy.robot.exceptionhandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import yy.robot.constant.ExceptionCodes;
import yy.robot.domain.ErrorResponse;
import yy.robot.exception.BizException;
import yy.robot.exception.EntityNotExistException;
import yy.robot.exception.LoginException;
import yy.robot.exception.SmsException;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/5/3 9:22
 */
public abstract class CommonExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    // ==================
    // Unknown exceptions
    // ==================

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object exception(Exception e) {
        logger.info("Unexpected exception: " + e.getClass().getName());
        e.printStackTrace();
        return new ErrorResponse(ExceptionCodes.BUSINESS_EXCEPTION, e.getMessage());
    }


    // ================
    // basic exceptions
    // ================

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object methodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        return new ErrorResponse(ExceptionCodes.METHOD_NOT_SUPPORTED, String.format("请求方法不支持: %s", e.getMethod()));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object illegalArgumentException(IllegalArgumentException e) {
        return new ErrorResponse(ExceptionCodes.ILLEGAL_ARGUMENT, String.format("参数错误: %s", e.getMessage()));
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object a(MethodArgumentTypeMismatchException e) {
        return new ErrorResponse(ExceptionCodes.ILLEGAL_ARGUMENT, String.format("参数格式错误: %s", e.getName()));
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object missingParameterException(MissingServletRequestParameterException e) {
        return new ErrorResponse(ExceptionCodes.ILLEGAL_ARGUMENT, String.format("缺少参数: %s(%s)", e.getParameterName(), e.getParameterType()));
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object entityNotExistException(DataIntegrityViolationException e) {
        return new ErrorResponse(ExceptionCodes.DATABASE_VIOLATION, "数据库冲突: " + e.getMessage());
    }

    // ===================
    // specific exceptions
    // ===================

    @ExceptionHandler(BizException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object bizException(BizException e) {
        return new ErrorResponse(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(LoginException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object loginException(Exception e) {
        return new ErrorResponse(ExceptionCodes.TOKEN_REQUIRED, e.getMessage());
    }

    @ExceptionHandler(EntityNotExistException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object entityNotExistException(EntityNotExistException e) {
        return new ErrorResponse(ExceptionCodes.ENTITY_NOT_EXIST, e.getMessage());
    }

    @ExceptionHandler(SmsException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object smsException(SmsException e) {
        return new ErrorResponse(ExceptionCodes.SMS_EXCEPTION, String.format("短信发送异常: %s", e.getMessage()));
    }
}
